function defaultToString (item) {
    if (item === null) {
      return `NULL`
    } else if (item === undefined) {
      return 'UNDEFINED'
    } else if (typeof item === 'string' || item instanceof String) {
      return `${item}`
    }
    return item.toString()
}

class ValuePair {
    constructor (key, value) {
      this.key = key
      this.value = value
    }
    toString () {
      return `{#${this.key}}: ${this.value}`
    }
}


class HashTable {
    constructor (toStrFn = defaultToString) {
      this.toStrFn = toStrFn
      this.table = {}
    }

    loseloseHashCode (key) {
        if (typeof key === 'number') {
            return key
        }
        const tableKey = this.toStrFn(key)
        let hash = 0
        for (let index = 0; index < tableKey.length; index++) {
            hash += tableKey.charCodeAt(index)
        }
        return hash % 37
    }
    hashCode (key) {
        return this.loseloseHashCode(key)
    }


    put (key, value) {
        if (key != null && value != null) {
          const hashCode = this.hashCode(key)
          this.table[hashCode] = new ValuePair(key, value)
          return true
        }
        return false
    }


    get (key) {
        const valuePair = this.table[this.hashCode(key)]
        return valuePair == null ? undefined : valuePair.value
    }


    remove (key) {
        const hashCode = this.hashCode(key)
        const valuePair = this.table[hashCode]
        if (valuePair != null) {
          delete this.table[hashCode]
          return true
        }
        return false
    }


}


const hash = new HashTable()
hash.put('AAA', 'AAA@qq.com')
hash.put('BBB', 'BBB@163.com')
hash.put('CCC', 'CCC@gmail.com')
console.log(hash.hashCode('AAA') + ' - AAA') // 10- AAA
console.log(hash.hashCode('BBB') + ' - BBB') // 13- BBB
console.log(hash.hashCode('CCC') + ' - CCC') // 16- CCC
console.log(hash.get('AAA'))                // AAA@qq.com
console.log(hash.get('BBB'))                // BBB@163.com
console.log(hash.get('CCC'))                // CCC@gmail.com
hash.remove('BBB')
console.log(hash.get('AAA'))                // AAA@qq.com
console.log(hash.get('BBB'))                // undefined
console.log(hash.get('CCC'))                // CCC@gmail.com


